﻿<cfsilent>
	<cfscript>
		
		mathAdvice = getProperty("serviceFactory").getBean("senateMathAdvice");
		
		/* 考试冲突比例设置 */
		finalCourseConflict = event.getArg("EXAM.FINAL.CourseConflict");
		
		if ( finalCourseConflict eq "" ) {
			finalCourseConflict = 0;
		}
		
		examId = event.getArg("EXID");

		/* 加载考试任务 */
		sql = "SELECT 
				a.exam_type, a.exidx, a.wid, a.wdidx, a.cellidx, a.term_id, a.examer_sum, a.campus_id, 
				b.cid, b.course_name 
				FROM t_examtask a 
				INNER JOIN t_course b ON a.cid = b.cid 
				WHERE 
					a.task_exid = :examId ";
		
		queryObj = new Query( datasource=application.dnsSlave ); 
		queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char" );
		
		rs_exam = queryObj.execute( sql=sql ).getResult();
		
		
		courseId = rs_exam.cid; /* 课程代码 */
		termId = rs_exam.term_id; /* 考试学期代码 */

		examType = rs_exam.exam_type; /* 考试类别 */
		examIdx = rs_exam.exidx; /* 考序号 */
		examWeek = rs_exam.wid; /* 考试周次 */
		examWeekDay = rs_exam.wdidx; /* 考试安排于星期几 */
		examCell = rs_exam.cellidx; /* 考试场次 */
		
		examerCount = rs_exam.examer_sum; /* 参加考试人数 */
		campusId = rs_exam.campus_id;  /* 考试安排校区 */


		/* 设置考试可用的时间 */
		timeTable = arrayNew(2);
		
		for( weekDay=1; weekDay lte 7; weekDay++ ){
			for( lecture=1; lecture lte 5; lecture++ ){
				timeTable[ weekDay ][ lecture ] = 0;
			}
		}

		/* 根据考试类型 选择加载时间设置数据 */
		switch ( examType ) {
			
			case "H":
				/* 读取半期考试可用时间 */
				/* 第3位 是否用于半期排考 */
				sql = "SELECT wdidx, lecidx FROM t_timetable WHERE SUBSTR(props, 3, 1) = '1' AND lecidx IN ('1','2','3','4','5') ";
				break;
				
			case "F":
				/* 读取期末考试可用时间 */
				/* 第4位 是否用于期末集中排考 */
				sql = "SELECT wdidx, lecidx FROM t_timetable WHERE SUBSTR(props, 4, 1) = '1' AND lecidx IN ('1','2','3','4','5') ";
				break;

			case "S":
				/* 读取分散考试可用时间 */
				/* 第5位 是否用于自主分散考试安排 */
				sql = "SELECT wdidx, lecidx FROM t_timetable WHERE SUBSTR(props, 5, 1) = '1' AND lecidx IN ('1','2','3','4','5') ";
				break;
		}
		
		queryObj = new Query( datasource=application.dnsSlave ); 

		rs_timeset = queryObj.execute( sql=sql ).getResult();
		
		for ( a=1; a LTE rs_timeset.recordCount; a++ ) {
			timeTable[ rs_timeset["wdidx"][a] ][ rs_timeset["lecidx"][a] ] = 1;
		}
		
		/* 如果当前已排考 则标注当前考试安排 */
		if ( examWeekDay neq "0" ) {
			timeTable[examWeekDay][examCell] = -1;
		}
		
		/* -------------- */
		/* 计算课表时间冲突 */
		/* -------------- */
		conflictSet = structNew();

		sql = "SELECT a.task_id FROM t_examplan a WHERE a.cid = :courseId AND a.term_id = :termId AND a.exidx = :examIdx ";
		
		queryObj = new Query( datasource=application.dnsSlave ); 
		queryObj.addParam( name="courseId", value=courseId, cfsqltype="cf_sql_varchar");
		queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char");
		queryObj.addParam( name="examIdx", value=examIdx, cfsqltype="cf_sql_char");

		rs_task = queryObj.execute( sql=sql ).getResult();
		
		/* 生成教学班号列表 */
		taskIds = "";
		
		for ( a=1; a LTE rs_task.recordCount; a++ ) {
			taskIds = listAppend( taskIds, rs_task["task_id"][a], "|" );
		}

		/* 检查现有考试冲突 */
		
		/* 学生不能同时安排两场考试 */
		
		sql = "SELECT DISTINCT a.wdidx, a.cellidx 
				FROM t_examtask a 
				WHERE 
					( a.task_exid > :examId or a.task_exid < :examId ) 
					AND 
					( a.wdidx > '0' or  a.wdidx < '0' ) 
					AND 
					a.wid = :examWeek 
					AND 
					a.term_id = :termId 
					AND 
					EXISTS (
						SELECT 1 FROM t_exammidplan b 
						WHERE 
							a.cid = b.cid 
							AND 
							a.term_id = b.term_id 
							AND 
							a.exidx = b.exidx 
							AND 
							EXISTS (
								SELECT 1 FROM t_student_course c 
								WHERE 
									b.task_id = c.task_id 
									AND 
									c.term_id = :termId 
									AND 
									EXISTS (
										SELECT 1 FROM t_student_course d 
										WHERE 
											c.stu_id = d.stu_id 
											AND 
											d.task_id IN ( :taskIds ) 
											AND 
											c.term_id = :termId 
											AND 
											d.term_id = :termId 
										) 
								) 
						) ";
		
		queryObj = new Query( datasource=application.dnsSlave ); 
		queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char");
		queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char");
		queryObj.addParam( name="examWeek", value=examWeek, cfsqltype="cf_sql_char");
		queryObj.addParam( name="taskIds", value=taskIds, cfsqltype="cf_sql_varchar", list=true, separator="|" );
		
		rs_stu_exam = queryObj.execute( sql=sql ).getResult();
		
		/* 标注期中考试冲突 */
		for ( a=1; a LTE rs_stu_exam.recordCount; a++ ) {
			
			weekDay = rs_stu_exam["wdidx"][a]; /* 星期几 */
			lecture = rs_stu_exam["cellidx"][a]; /* 第几场 */
			
			if ( timeTable[weekDay][lecture] eq 1 ) {
				timeTable[ weekDay ][ lecture ] = -3;
			}
		}
		
		
		/* 检查期末考试冲突 */
		sql = "SELECT DISTINCT a.wdidx, a.cellidx 
				FROM t_examtask a 
				WHERE 
					( a.task_exid > :examId or a.task_exid < :examId ) 
					AND 
					( a.wdidx > '0' or  a.wdidx < '0' ) 
					AND 
					a.wid = :examWeek 
					AND 
					a.term_id = :termId 
					AND 
					EXISTS (
						SELECT 1 FROM t_examplan b 
						WHERE 
							a.cid = b.cid 
							AND 
							a.term_id = b.term_id 
							AND 
							a.exidx = b.exidx 
							AND 
							EXISTS (
								SELECT 1 FROM t_student_course c 
								WHERE 
									b.task_id = c.task_id 
									AND 
									c.term_id = :termId 
									AND 
									EXISTS (
										SELECT 1 FROM t_student_course d 
										WHERE 
											c.stu_id = d.stu_id 
											AND 
											d.task_id IN ( :taskIds ) 
											AND 
											c.term_id = :termId 
											AND 
											d.term_id = :termId 
										) 
								) 
						) ";
		
		queryObj = new Query( datasource=application.dnsSlave ); 
		queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char");
		queryObj.addParam( name="examId", value=examId, cfsqltype="cf_sql_char");
		queryObj.addParam( name="examWeek", value=examWeek, cfsqltype="cf_sql_char");
		queryObj.addParam( name="taskIds", value=taskIds, cfsqltype="cf_sql_varchar", list=true, separator="|" );
		
		rs_stu_exam = queryObj.execute( sql=sql ).getResult();
		
		/* 标注期末考试冲突 */
		for ( a=1; a LTE rs_stu_exam.recordCount; a++ ) {
			
			weekDay = rs_stu_exam["wdidx"][a]; /* 星期几 */
			lecture = rs_stu_exam["cellidx"][a]; /* 第几场 */
			
			if ( timeTable[weekDay][lecture] eq 1 ) {
				timeTable[ weekDay ][ lecture ] = -3;
			}
		}

		/* 考试时间 学生不能有课 */
		
		/* 生成考试学生课表时间冲突 */
		sql = "SELECT 
				a.tasktime, COUNT( DISTINCT b.stu_id ) stu_count
				FROM t_task_timetable a 
				INNER JOIN t_student_course b ON a.task_id = b.task_id 
				INNER JOIN t_task_arrange c ON c.task_id = a.task_id 
				WHERE 
					c.term_id = :termId 
					AND 
					SUBSTR( a.widx, " & int(examWeek) & ", 1) = '1' 
					AND 
					EXISTS ( 
						SELECT 1 FROM t_student_course d 
						WHERE 
							b.stu_id = d.stu_id 
							AND 
							d.task_id IN ( :taskIds ) 
							AND 
							b.term_id = :termId 
							AND 
							d.term_id = :termId 
					) 
				GROUP BY a.tasktime";
		
		queryObj = new Query( datasource=application.dnsSlave ); 
		queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char");
		queryObj.addParam( name="taskIds", value=taskIds, cfsqltype="cf_sql_varchar", list=true, separator="|" );
		
		rs_stu_course = queryObj.execute( sql=sql ).getResult();
		
		for ( a=1; a LTE rs_stu_course.recordCount; a++ ) {
			
			taskTime = rs_stu_course["tasktime"][a]; /* 上课时间 */
			studentCount = rs_stu_course["stu_count"][a]; /* 冲突学生人数 */

			weekDay = listGetAt( taskTime, 1, "-@" ); /* 星期几 */
			lecture = listGetAt( taskTime, 2, "-@" ); /* 第几讲 */
			cellLength = listGetAt( taskTime, 3, "-@" ); /* 讲次长度 */

			switch ( cellLength ) {
				
				case "2":
					
					/* 若第六节有课 则冲突计算至第五场 */
					if ( lecture eq 6 ) { 
						sKey = "STU_" & weekDay & "@" & 5;
					}
					else {
						sKey = "STU_" & weekDay & "@" & lecture;
					}
					

					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					/* 标志该时间学生上课冲突 */
					if ( lecture eq 6 ) {
						
						if ( timeTable[weekDay][5] eq 1 ) {
							timeTable[weekDay][5] = -2;
						}

					}
					else {
						
						if ( timeTable[weekDay][lecture] eq 1 ) {
							timeTable[weekDay][lecture] = -2;
						}
						
					}

					break;
				
				case "3":
					
					sKey = "STU_" & weekDay & "@" & lecture;
					
					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					/* 标志该时间学生上课冲突 */
					if ( timeTable[weekDay][lecture] eq 1 ) {
						timeTable[ weekDay ][ lecture ] = -2;
					}
					
					break;
				
				case "4":
				case "5":
					
					sKey = "STU_" & weekDay & "@" & lecture;
					
					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					/* 4/5节连排 则冲突延续一次 */
					sKey = "STU_" & weekDay & "@" & lecture + 1;
					
					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					/* 标志该时间学生上课冲突 */
					if ( timeTable[weekDay][lecture] eq 1 ) {
						timeTable[ weekDay ][ lecture ] = -2;
					}
					if ( lecture < 5 AND timeTable[weekDay][lecture + 1] eq 1 ) {
						timeTable[ weekDay ][ lecture + 1 ] = -2;
					}
					
					break;
				
				case "8":
					
					sKey = "STU_" & weekDay & "@" & lecture;
					
					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					/* 8节连排 则冲突延续3次 */
					sKey = "STU_" & weekDay & "@" & lecture + 1;
					
					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					sKey = "STU_" & weekDay & "@" & lecture + 2;
					
					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					sKey = "STU_" & weekDay & "@" & lecture + 3;
					
					if ( structKeyExists( conflictSet, sKey ) ) {
						conflictSet[sKey] += studentCount;
					}
					else {
						structInsert( conflictSet, sKey, studentCount );
					}
					
					/* 标志该时间学生上课冲突 */
					if ( timeTable[weekDay][lecture] eq 1 ) {
						timeTable[ weekDay ][ lecture ] = -2;
					}
					if ( lecture LT 5 AND timeTable[weekDay][lecture + 1] eq 1 ) {
						timeTable[ weekDay ][ lecture + 1 ] = -2;
					}
					if ( lecture LT 4 AND timeTable[weekDay][lecture + 2] eq 1 ) {
						timeTable[ weekDay ][ lecture + 2 ] = -2;
					}
					if ( lecture LT 3 AND timeTable[weekDay][lecture + 3] eq 1 ) {
						timeTable[ weekDay ][ lecture + 3 ] = -2;
					}
					
					break;
			}
			
		}


		/* 检查教室是否足够 */

		for(weekDay=1; weekDay lte 7; weekDay++){
			for(lecture=1; lecture lte 5; lecture++){
				
				if ( timeTable[weekDay][lecture] eq 1 ) {
					
					cells = 2;
					/* 如果为 第二讲 或 第五讲 则使用最长学时数 */
					if (lecture eq 2 or lecture eq 5) { cells = 3; }
					
					cellStart = mathAdvice.convertLectureIdxToCellStart(lecture);
					cellEnd = cellStart + cells -1;
					
					sql = "SELECT 
							CASE WHEN SUM(a.sits_exam) IS NULL THEN 0 ELSE SUM(a.sits_exam) END sit_count 
							FROM t_classroom a 
							WHERE 
								SUBSTR(a.cr_usage, 3, 1) = '1' 
								AND 
								a.campus_id = :campusId 
								AND 
								NOT EXISTS (
									SELECT 1 FROM t_clsroom_timetable b 
									WHERE 
										a.cr_id = b.cr_id 
										AND 
										b.term_id = :termId 
										AND 
										b.wdidx = :weekDay 
										AND 
										NOT ( cellidx + cellrelay -1 < :cellStart OR cellidx > :cellEnd )
										AND 
										SUBSTR( b.widx, " & int(examWeek) & ", 1)  = '1'
									) ";
					
					queryObj = new Query( datasource=application.dnsSlave ); 
					queryObj.addParam( name="termId", value=termId, cfsqltype="cf_sql_char");
					queryObj.addParam( name="weekDay", value=weekDay, cfsqltype="cf_sql_char");
					queryObj.addParam( name="campusId", value=campusId, cfsqltype="cf_sql_char");
					queryObj.addParam( name="cellStart", value=cellStart, cfsqltype="cf_sql_integer");
					queryObj.addParam( name="cellEnd", value=cellEnd, cfsqltype="cf_sql_integer");

					rs_room_check = queryObj.execute( sql=sql ).getResult();

					/* 如果可用考场座位数 没有超过应考人数10 */
					if ( timeTable[weekDay][lecture] eq 1 AND rs_room_check.sit_count lt examerCount + 10 ) {
						timeTable[weekDay][lecture] = -4;
					}

				}
			
			}
		}

		
		backArgs = structNew();

		/* 对于 javascript 地址 &amp; 需要重新转义为 & 避免 google chrome 浏览器无法正确识别地址 */
		backURL = replace( buildURL( "examArrange", backArgs), "&amp;", "&", "all");

	</cfscript>
</cfsilent>

<table class="UICourseTable">
	<thead>
		<tr>
			<td colspan="2" width="2%"></td>
			<td width="14%">星期一</td>
			<td width="14%">星期二</td>
			<td width="14%">星期三</td>
			<td width="14%">星期四</td>
			<td width="14%">星期五</td>
			<td width="14%">星期六</td>
			<td width="14%">星期天</td>
		</tr>
	</thead>
	<tbody>
		<cfloop from="1" to="5" index="lec">
			<tr>
				<cfswitch expression="#lec#">
					<cfcase value="1">
					<td rowspan="2"><cfoutput>#mathAdvice.convertLectureIdxToDayPart(lec)#</cfoutput></td>
					</cfcase>
					<cfcase value="3">
						<td rowspan="2"><cfoutput>#mathAdvice.convertLectureIdxToDayPart(lec)#</cfoutput></td>
					</cfcase>
					<cfcase value="5">
						<td rowspan="1"><cfoutput>#mathAdvice.convertLectureIdxToDayPart(lec)#</cfoutput></td>
					</cfcase>
				</cfswitch>
				<td><cfoutput>#mathAdvice.convertExamIdxToChinese(lec)#</cfoutput></td>
				<cfloop from="1" to="7" index="wkday">
					<td <cfif timeTable[wkday][lec] eq 1>class="available"</cfif>>
					
						<!--- 如果学生上课时间冲突 --->
						<cfif timeTable[wkday][lec] eq -2>
							<cfset percent = int(1000 * conflictSet["STU_#wkday#@#lec#"] / examerCount)/10 />
							<!--- 如是期末考试 并且冲突百分比满足设置 则依然允许排考 --->
							<cfif examType eq "F" and percent lt finalCourseConflict>
								<a class="botton force" href="javascript:addTimeCell(<cfoutput>#wkday#</cfoutput>,<cfoutput>#lec#</cfoutput>);">可排</a>
								<br/>
							</cfif>
							<span>有课</span>
							<span class="numeric">(<cfoutput>#conflictSet["STU_#wkday#@#lec#"]#</cfoutput>)</span>
						</cfif>

						<!--- 如果学生有考试 --->
						<cfif timeTable[wkday][lec] eq -3>
							<span>考试</span>
						</cfif>
						
						<!--- 如果教室不足 --->
						<cfif timeTable[wkday][lec] eq -4>
							<span>考场不足</span>
						</cfif>
						
						<!--- 如果已安排 --->
						<cfif timeTable[wkday][lec] eq -1>
							<a href="javascript:removeTimeCell(<cfoutput>#wkday#</cfoutput>,<cfoutput>#lec#</cfoutput>);"><cfoutput>#rs_exam.course_name#</cfoutput></a>
						</cfif>
						
						<!--- 如果时间可用 --->
						<cfif timeTable[wkday][lec] eq 1>
							<a class="botton yes" href="javascript:addTimeCell(<cfoutput>#wkday#</cfoutput>,<cfoutput>#lec#</cfoutput>);">可排</a>
						</cfif>
						
						<!--- 不允许排考 --->
						<cfif timeTable[wkday][lec] eq 0>
							<span>禁止排考</span>
						</cfif>
						
					</td>
				</cfloop>
			</tr>
		</cfloop>
	</tbody>
</table>
<div id="out"></div>
<script language="javascript" type="text/javascript">
	//<![CDATA[
	<!--
	
	function removeTimeCell(weekDay, lecture){
		
		$.post(
				"<cfoutput>#buildURL('apiExamTaskClear')#</cfoutput>", 
				{
					'exid' : '<cfoutput>#examId#</cfoutput>',
					'seed': (new Date()).getTime()
				}, 
				function(data) {
					
					//$("#out").html(data);

					result = $.parseJSON(data);
										
					if (result.success) {
						/* 刷新排课数据 */
						window.location.reload();
					}
					else {
						alert(result.reason);
					}
					
				});
		
		
	}
	
	function addTimeCell(weekDay, lecture){
		
		$.post(
				"<cfoutput>#buildURL('apiExamTaskSetTime')#</cfoutput>", 
				{
					'wkday' : weekDay,
					'lec' : lecture,
					'exid' : '<cfoutput>#examId#</cfoutput>',
					'seed': (new Date()).getTime()
				}, 
				function(data) {

					//$("#out").html(data);

					result = $.parseJSON(data);
					
					if (result.success) {

						/* 返回排课任务列表 */
						window.location = '<cfoutput>#backURL#</cfoutput>';
					
					}
					else {
						alert(result.reason);
					}

				});
		
	}	
	
	// -->
	//]]>
</script>
	